﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.Composition;
using System.Collections.ObjectModel;

namespace AlbumArtOrganizer.Plugins.Google.ImageFinder
{
    [Export(typeof(AlbumArtOrganizer.ImageFinder.IImageFinder))]
    public class ImageFinder : AlbumArtOrganizer.ImageFinder.ImageFinder, AlbumArtOrganizer.ImageFinder.IImageFinder
    {
        public const string OPTIONCONTRACTNAME = "ImageFinderGoogleOption";

        public override string Name
        {
            get
            {
                return "Google";
            }
            set
            {
            }
        }

        public override bool IsSearchAvailable
        {
            get
            {
                return true;
            }
            set
            {
            }
        }

        AlbumArtOrganizer.Model.IAlbum _currentAlbum = null;
        AlbumArtOrganizer.Model.IAlbum _previousAlbum = null;
        public override AlbumArtOrganizer.Model.IAlbum CurrentAlbum
        {
            get
            {
                return _currentAlbum;
            }
            set
            {
                _previousAlbum = _currentAlbum;
                _currentAlbum = value;
                OnPropertyChanged("CurrentAlbum");
                OnPropertyChanged("IsSearchAvailable");
            }
        }

        [ImportMany(OPTIONCONTRACTNAME, typeof(AlbumArtOrganizer.Model.IOption))]
        public override ObservableCollection<AlbumArtOrganizer.Model.IOption> Options
        {
            get;
            set;
        }

        public override string GetSearchString(string artistName, string albumTitle)
        {
            var optionSearchFormatString = Options.FirstOrDefault(option => option is Model.OptionSearchFormatString) as Model.OptionSearchFormatString;
            if (optionSearchFormatString != null)
            {
                return String.Format(optionSearchFormatString.Value, artistName, albumTitle);
            }
            else
            {
                return String.Format("\"{0}\" \"{1}\" cover", artistName, albumTitle);
            }
        }

        public override AlbumArtOrganizer.ImageFinder.IImageFinderResults FindImages(string artistName, string albumTitle)
        {
            var resultCount = 25;
            var offset = 0;
            var searchString = GetSearchString(artistName, albumTitle);
            dynamic restClient = GetRestClient();
            dynamic searchOptions = GetSearchOptions(searchString, resultCount, offset, Options);
            dynamic response = GetSearchResults(restClient, searchOptions);
            var images = new List<AlbumArtOrganizer.Model.IImage>();
            foreach (dynamic result in response.responseData.results)
            {
                images.Add(new Image()
                           {
                               ThumbnailLocation = new Uri(result.tbUrl),
                               FullSizeLocation = new Uri(result.unescapedUrl),
                               FullSizeWidth = Int32.Parse(result.width),
                               FullSizeHeight = Int32.Parse(result.height)
                           });
            }
            var imageResults = new ImageFinderResults()
            {
                Images = images,
                TotalResultsCount = images.Count,
                Offset = offset
            };
            return imageResults;
        }

        dynamic GetRestClient()
        {
            dynamic restClient = new DynamicRest.RestClient("http://ajax.googleapis.com/ajax/services/{operation}/images?v=1.0", DynamicRest.RestClientMode.Json);
            return restClient;
        }

        dynamic GetSearchOptions(string searchString, int resultCount, int offset, IEnumerable<AlbumArtOrganizer.Model.IOption> options)
        {
            dynamic searchOptions = new DynamicRest.JsonObject();
            searchOptions.q = searchString;
            var optionImageSize = options.FirstOrDefault(option => option is Model.OptionImageSize) as Model.OptionImageSize;
            if (optionImageSize != null)
            {
                var sizeValue = optionImageSize.GetSearchValue();
                // icon; small|medium|large|xlarge; xxlarge; huge
                searchOptions.imgsz = sizeValue;
            }
            searchOptions.rsz = "large"; // Result set size
            searchOptions.start = 0; // Offset
            var optionSafeSearch = options.FirstOrDefault(option => option is Model.OptionSafeSearch) as Model.OptionSafeSearch;
            if (optionSafeSearch != null)
            {
                var safeValue = optionSafeSearch.GetSearchString();
                searchOptions.safe = safeValue;
            }
            return searchOptions;
        }

        dynamic GetSearchResults(dynamic restClient, dynamic searchOptions)
        {
            dynamic response = restClient.search(searchOptions);
            return response;
        }
    }
}
